package com.boot.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.boot.common.constant.GlobalVar;
import com.boot.common.constant.MessageConstant;
import com.boot.common.constant.RedisConstant;
import com.boot.common.result.Result;
import com.boot.system.entity.SysDict;
import com.boot.system.mapper.DictMapper;
import com.boot.system.service.DictService;
import com.boot.util.ConvertUtil;
import com.boot.util.RedisUtil;
import com.boot.util.SecurityUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service("dictService")
public class DictServiceImpl extends ServiceImpl<DictMapper, SysDict> implements DictService {

    private final RedisUtil redisUtil;

    /**
     * 系统启动完成后，加载字典列表缓存
     */
    @PostConstruct
    public void initDict() {
        QueryWrapper query = QueryWrapper.create().from(SysDict.class);
        query.eq("status", 1);
        List<SysDict> list = this.list(query);
        for (SysDict sysDict : list){
            String key = StrUtil.format(RedisConstant.Dict.INFO, sysDict.getId(), sysDict.getCode());
            redisUtil.set(key, sysDict);
        }
        log.info("字典列表加载完成！");
    }

    @Override
    public Page<SysDict> getDictPage(Map<String, Object> queryParam) {
        // 基础参数
        int pageNum = (int) queryParam.getOrDefault("pageNum", 1);
        int pageSize = (int) queryParam.getOrDefault("pageSize", 10);
        // 查询条件
        QueryWrapper query = QueryWrapper.create().from(SysDict.class);
        // 模糊查询
        query.and(q -> q.and(SysDict::getName).like(queryParam.get("keywords"))
                        .or(SysDict::getCode).like(queryParam.get("keywords"))
                        .or(SysDict::getRemark).like(queryParam.get("keywords")),
                ObjectUtil.isNotEmpty(queryParam.get("keywords")));
        if (ObjectUtil.isNotEmpty(queryParam.get("status"))) {
            // 状态
            query.eq("status", queryParam.get("status"));
        }
        query.orderBy((String) queryParam.getOrDefault("orderBy", "update_time desc, id desc"));
        return this.page(new Page<>(pageNum, pageSize), query);
    }

    @Override
    public Result<?> addDict(Map<String, Object> dataParam) {
        //判断编码是否已存在
        if (dataParam.get("code") != null) {
            SysDict sysDictTemp = this.mapper.selectByCode((String) dataParam.get("code"));
            if (sysDictTemp != null) {
                //已存在
                return Result.error(MessageConstant.DICT_EXIST);
            }
        }
        SysDict sysDict = ConvertUtil.mapToClass(dataParam, SysDict.class);
        sysDict.setItems(JSONUtil.toJsonStr(dataParam.get("items")));
        sysDict.setCreateBy(SecurityUtil.getUid());
        sysDict.setCreateTime(GlobalVar.systemTime);
        sysDict.setUpdateBy(SecurityUtil.getUid());
        sysDict.setUpdateTime(GlobalVar.systemTime);
        boolean result = this.save(sysDict);
        if (result){
            //设置缓存
            this.setCache(sysDict.getId());
        }
        return Result.success(result);
    }

    @Override
    public Result<?> updateDict(Map<String, Object> dataParam) {
        //查询原数据
        SysDict oldSysDict = this.getById(Long.valueOf(dataParam.get("id").toString()));
        //判断是否可以修改
        if (dataParam.get("code") != null && !dataParam.get("code").equals(oldSysDict.getCode())) {
            SysDict sysDictTemp = this.mapper.selectByCode((String) dataParam.get("code"));
            if (sysDictTemp != null) {
                //已存在
                return Result.error(MessageConstant.DICT_EXIST);
            }
        }
        SysDict sysDict = ConvertUtil.mapToClass(dataParam, SysDict.class);
        sysDict.setItems(JSONUtil.toJsonStr(dataParam.get("items")));
        sysDict.setUpdateBy(SecurityUtil.getUid());
        sysDict.setUpdateTime(GlobalVar.systemTime);
        boolean result = this.updateById(sysDict);
        if (result){
            //更新缓存
            this.deleteCache(Collections.singletonList(sysDict.getId()));
            this.setCache(sysDict.getId());
        }
        return Result.success(result);
    }

    @Override
    public boolean deleteDict(String ids) {
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .collect(Collectors.toList());
        //先删除缓存
        this.deleteCache(idList);
        //数据库-逻辑删除
        return this.removeByIds(idList);
    }

    @Override
    public List<SysDict> getCacheList() {
        List<SysDict> list = new ArrayList<>();
        String prefix = StrUtil.format(RedisConstant.Dict.INFO, "*", "*");
        Set<String> keys = redisUtil.getKeys(prefix);
        for (String key : keys) {
            SysDict sysDict = (SysDict) redisUtil.get(key);
            list.add(sysDict);
        }
        return list;
    }

    @Override
    public SysDict getCache(String code) {
        String prefix = StrUtil.format(RedisConstant.Dict.INFO, "*", code);
        //获取真实的缓存Key
        String key = null;
        Set<String> keys = redisUtil.getKeys(prefix);
        for (String item : keys) {
            key = item;
        }
        if (key != null) {
            return (SysDict) redisUtil.get(key);
        }
        return null;
    }

    @Override
    public void setCache(Long id) {
        SysDict sysDict = this.getById(id);
        if (sysDict != null){
            String key = StrUtil.format(RedisConstant.Dict.INFO, sysDict.getId(), sysDict.getCode());
            redisUtil.set(key, sysDict);
        }
    }

    @Override
    public void deleteCache(List<Long> ids) {
        for (Long id : ids){
            String prefix = StrUtil.format(RedisConstant.Dict.INFO, id, "*");
            //获取真实的缓存Key
            String key = null;
            Set<String> keys = redisUtil.getKeys(prefix);
            for (String item : keys) {
                key = item;
            }
            if (key != null) {
                //删除
                redisUtil.delete(key);
            }
        }
    }
}
